#include "../SeanNetworkLib/SeanNetwork.h"
#include <iostream>
#include <thread>
#include <atomic>
#include <string>
#include <mutex>

// 消息ID定义
enum MessageType {
    MSG_HEARTBEAT = 0,
    MSG_TEXT = 1,
    MSG_FILE_REQUEST = 2,
    MSG_FILE_RESPONSE = 3
};

// 统计信息输出
void PrintStats(NBNetwork::NetworkStats stats, NBNetwork::ChannelType channel) {
    std::string channelName = (channel == NBNetwork::ChannelType::KCP) ? "KCP" : "TCP";
    std::cout << "==== " << channelName << " Channel Stats ====" << std::endl;
    std::cout << "Total Bytes Sent: " << stats.TotalBytesSent << std::endl;
    std::cout << "Total Bytes Received: " << stats.TotalBytesReceived << std::endl;
    std::cout << "Messages Sent: " << stats.MessagesSent << std::endl;
    std::cout << "Messages Received: " << stats.MessagesReceived << std::endl;
    std::cout << "Packet Loss: " << stats.PacketLoss << std::endl;
    std::cout << "Retransmissions: " << stats.Retransmissions << std::endl;
    std::cout << "Average RTT: " << stats.AverageRtt << " ms" << std::endl;
    std::cout << "Latest RTT: " << stats.LatestRtt << " ms" << std::endl;
    std::cout << "==============================" << std::endl;
}

int main(int argc, char* argv[]) {
    std::cout << "NBNetwork Client Test Application" << std::endl;
    std::cout << "=================================" << std::endl;

    // 解析命令行参数
    std::string serverHost = "127.0.0.1";
    uint16_t serverPort = 19000;

    if (argc >= 2) {
        serverHost = argv[1];
    }
    if (argc >= 3) {
        serverPort = static_cast<uint16_t>(std::stoi(argv[2]));
    }

    std::cout << "Connecting to server: " << serverHost << ":" << serverPort << std::endl;

    // 创建并配置客户端
    NBNetwork::NetworkConfig config;
    config.KcpMaxPacketLoss = 3;     // 最大连续丢包数
    config.KcpMaxLatency = 500;      // 最大延迟(ms)
    config.WorkerThreadCount = 2;    // 工作线程数

    // 创建客户端实例
    auto client = NBNetwork::Net::CreateClient(config);
    if (!client) {
        std::cerr << "Failed to create client" << std::endl;
        return 1;
    }

    // 互斥锁，保护控制台输出
    std::mutex consoleMutex;

    // 注册消息处理回调
    client->RegisterMessageHandler(MSG_TEXT, [&consoleMutex](std::shared_ptr<NBNetwork::NetworkMessage> message) {
        // 从消息中提取文本内容
        std::string text = NBNetwork::Net::GetMessageAsString(message);
        
        // 线程安全的控制台输出
        std::lock_guard<std::mutex> lock(consoleMutex);
        std::cout << "Received text message: " << text << std::endl;
    });

    client->RegisterMessageHandler(MSG_FILE_RESPONSE, [&consoleMutex](std::shared_ptr<NBNetwork::NetworkMessage> message) {
        // 这里只是演示，实际应用中可以处理文件内容
        std::lock_guard<std::mutex> lock(consoleMutex);
        std::cout << "Received file data, size: " << message->GetBodySize() << " bytes" << std::endl;
    });

    // 注册连接状态回调
    client->SetConnectionCallback([&consoleMutex](NBNetwork::ConnectionState state, const std::string& reason) {
        std::lock_guard<std::mutex> lock(consoleMutex);
        std::cout << "Connection state changed: ";
        
        switch (state) {
            case NBNetwork::ConnectionState::Connected:
                std::cout << "Connected";
                break;
            case NBNetwork::ConnectionState::Connecting:
                std::cout << "Connecting";
                break;
            case NBNetwork::ConnectionState::Disconnected:
                std::cout << "Disconnected";
                break;
            case NBNetwork::ConnectionState::Reconnecting:
                std::cout << "Reconnecting";
                break;
            case NBNetwork::ConnectionState::Failed:
                std::cout << "Failed";
                break;
            default:
                std::cout << "Unknown";
                break;
        }
        
        if (!reason.empty()) {
            std::cout << " (" << reason << ")";
        }
        std::cout << std::endl;
    });

    // 启用自动重连
    client->SetAutoReconnect(true, 10, 1000);

    // 启动客户端
    if (!client->Start()) {
        std::cerr << "Failed to start client" << std::endl;
        return 1;
    }

    // 连接到服务器
    if (!client->Connect(serverHost, serverPort)) {
        std::cerr << "Failed to initiate connection" << std::endl;
        return 1;
    }

    std::cout << "Client started, entering command loop" << std::endl;
    std::cout << "Type 'help' for available commands" << std::endl;

    std::string line;
    bool running = true;
    
    // 主循环
    while (running && std::getline(std::cin, line)) {
        // 跳过空行
        if (line.empty()) {
            continue;
        }

        // 解析命令
        std::string command = line;
        std::string param;

        size_t spacePos = line.find(' ');
        if (spacePos != std::string::npos) {
            command = line.substr(0, spacePos);
            param = line.substr(spacePos + 1);
        }

        // 执行命令
        if (command == "quit" || command == "exit") {
            std::cout << "Exiting..." << std::endl;
            running = false;
        }
        else if (command == "help") {
            std::cout << "Available commands:" << std::endl;
            std::cout << "  help                - Show this help" << std::endl;
            std::cout << "  send <message>      - Send text message" << std::endl;
            std::cout << "  request <filename>  - Request a file" << std::endl;
            std::cout << "  stats               - Show network statistics" << std::endl;
            std::cout << "  switch              - Switch channel (KCP/TCP)" << std::endl;
            std::cout << "  status              - Show connection status" << std::endl;
            std::cout << "  reconnect           - Force reconnection" << std::endl;
            std::cout << "  quit                - Exit the application" << std::endl;
        }
        else if (command == "send" && !param.empty()) {
            // 创建文本消息
            auto message = client->CreateMessage(MSG_TEXT, NBNetwork::MessagePriority::Normal);
            message->SetBody(reinterpret_cast<const uint8_t*>(param.data()), param.size());
            
            // 发送消息
            if (client->SendMsg(message)) {
                std::cout << "Message sent" << std::endl;
            } else {
                std::cout << "Failed to send message" << std::endl;
            }
        }
        else if (command == "request" && !param.empty()) {
            // 创建文件请求消息
            auto message = client->CreateMessage(MSG_FILE_REQUEST, NBNetwork::MessagePriority::High);
            message->SetBody(reinterpret_cast<const uint8_t*>(param.data()), param.size());
            
            // 发送请求
            if (client->SendMsg(message)) {
                std::cout << "File request sent for: " << param << std::endl;
            } else {
                std::cout << "Failed to send file request" << std::endl;
            }
        }
        else if (command == "stats") {
            auto stats = client->GetNetworkStats();
            auto channelType = client->GetCurrentChannelType();
            PrintStats(stats, channelType);
        }
        else if (command == "switch") {
            // 切换通道
            NBNetwork::ChannelType currentChannel = client->GetCurrentChannelType();
            NBNetwork::ChannelType targetChannel = (currentChannel == NBNetwork::ChannelType::KCP) ? 
                                                 NBNetwork::ChannelType::TCP : NBNetwork::ChannelType::KCP;
            
            if (client->SwitchChannel(targetChannel)) {
                std::string channelName = (targetChannel == NBNetwork::ChannelType::KCP) ? "KCP" : "TCP";
                std::cout << "Switched to " << channelName << " channel" << std::endl;
            } else {
                std::cout << "Failed to switch channel" << std::endl;
            }
        }
        else if (command == "status") {
            NBNetwork::ConnectionState state = client->GetConnectionState();
            NBNetwork::ChannelType channelType = client->GetCurrentChannelType();
            
            std::cout << "Connection state: ";
            switch (state) {
                case NBNetwork::ConnectionState::Connected:
                    std::cout << "Connected";
                    break;
                case NBNetwork::ConnectionState::Connecting:
                    std::cout << "Connecting";
                    break;
                case NBNetwork::ConnectionState::Disconnected:
                    std::cout << "Disconnected";
                    break;
                case NBNetwork::ConnectionState::Reconnecting:
                    std::cout << "Reconnecting";
                    break;
                case NBNetwork::ConnectionState::Failed:
                    std::cout << "Failed";
                    break;
                default:
                    std::cout << "Unknown";
                    break;
            }
            
            std::string channelName = (channelType == NBNetwork::ChannelType::KCP) ? "KCP" : "TCP";
            std::cout << " using " << channelName << " channel" << std::endl;
        }
        else if (command == "reconnect") {
            // 先断开
            client->Disconnect();
            
            // 重新连接
            if (client->Connect(serverHost, serverPort)) {
                std::cout << "Reconnection initiated" << std::endl;
            } else {
                std::cout << "Failed to initiate reconnection" << std::endl;
            }
        }
        else {
            std::cout << "Unknown command. Type 'help' for available commands" << std::endl;
        }
    }

    // 断开连接并停止客户端
    client->Disconnect();
    client->Stop();
    
    std::cout << "Client stopped" << std::endl;
    return 0;
}